#ifndef BOOT_PAGING_HPP
#define BOOT_PAGING_HPP

#include <std/cstddef>
#include <kernel/arch/i386/memory/paging/paging.hpp>
namespace bootPaging
{
constexpr size_t kernelPageTablesNumber{16};
extern "C" alignas(::paging::pageSize) [[gnu::section(".bootBss")]]
uint32_t kernelPageDirectory[::paging::entriesNumber];
static_assert(sizeof(kernelPageDirectory) == ::paging::pageSize, "The page directory must fit in one page.");
extern "C" alignas(::paging::pageSize) [[gnu::section(".bootBss")]]
uint32_t kernelPageTables[kernelPageTablesNumber][::paging::entriesNumber];
static_assert(sizeof(kernelPageTables[0]) == ::paging::pageSize, "The page tables must fit in one page.");

extern "C" void* lowKernelStart;
extern "C" void* lowKernelEnd;

[[gnu::section(".bootBss")]]
extern size_t usedPageTables;

constexpr uint16_t kernelPagingFlags{::paging::Flags::Present | ::paging::Flags::ReadWrite | ::paging::Flags::UserSupervisor};
extern "C" [[gnu::section(".bootText")]]
void initKernelPaging();

[[gnu::section(".bootText")]]
void mapMemory(uintptr_t start, uintptr_t end, bool higherHalf);
#define BOOTSTRAP_MAKE_ENTRY(address, flags) (reinterpret_cast<uint32_t>((address)) & 0xFFFFF000) | ((flags) & 0xFFF)

#define BOOTSTRAP_ALIGN_DOWN(address) ((address) & ~(::paging::pageSize - 1UL))

#define BOOTSTRAP_ALIGN_UP(address) (BOOTSTRAP_ALIGN_DOWN((address) + ::paging::pageSize - 1UL))

}

#endif
